package org.cboard.services;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.cboard.dao.BoardDao;
import org.cboard.dao.WidgetDao;
import org.cboard.dto.ViewDashboardBoard;
import org.cboard.dto.ViewDashboardWidget;
import org.cboard.pojo.DashboardBoard;
import org.cboard.pojo.DashboardWidget;
import org.cboard.security.token.TokenUtils;
import org.cboard.services.persist.PersistContext;
import org.cboard.services.persist.excel.XlsProcessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * Created by yfyuan on 2016/8/23.
 */
@Repository
public class BoardService {

    @Autowired
    private BoardDao boardDao;

    @Autowired
    private WidgetDao widgetDao;

    @Autowired
    private PersistService persistService;

//    @Value("${publish.address}")
//    private String serverAddress;

    @Value("${publish.path}")
    private String publishPath;
    @Autowired
    private XlsProcessService xlsProcessService;

    public List<DashboardBoard> getBoardList(String userId) {
        return boardDao.getBoardList(userId);
    }

    public ViewDashboardBoard getBoardData(Long id) {
        DashboardBoard board = boardDao.getBoard(id);
        JSONObject layout = JSONObject.parseObject(board.getLayout());
        JSONArray rows = layout.getJSONArray("rows");
        for (Object row : rows) {
            JSONObject o = (JSONObject) row;
            if ("param".equals(o.getString("type"))) {
                continue;
            }
            JSONArray widgets = o.getJSONArray("widgets");
            for (Object w : widgets) {
                JSONObject ww = (JSONObject) w;
                Long widgetId = ww.getLong("widgetId");
                DashboardWidget widget = widgetDao.getWidget(widgetId);
//                JSONObject dataJson = JSONObject.parseObject(widget.getData());
                //DataProviderResult data = dataProviderService.getData(dataJson.getLong("datasource"), Maps.transformValues(dataJson.getJSONObject("query"), Functions.toStringFunction()));
                JSONObject widgetJson = (JSONObject) JSONObject.toJSON(new ViewDashboardWidget(widget));
                //widgetJson.put("queryData", data.getData());
                ww.put("widget", widgetJson);
                ww.put("show", false);
            }
        }
        ViewDashboardBoard view = new ViewDashboardBoard(board);
        view.setLayout(layout);
        return view;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public ServiceStatusWithData save(String userId, String json) {
        JSONObject jsonObject = JSONObject.parseObject(json);
        DashboardBoard board = new DashboardBoard();
        board.setUserId(userId);
        board.setName(jsonObject.getString("name"));
        board.setCategoryId(jsonObject.getLong("categoryId"));
        board.setLayout(jsonObject.getString("layout"));

        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("user_id", board.getUserId());
        paramMap.put("board_name", board.getName());
        if (boardDao.countExistBoardName(paramMap) <= 0) {
            boardDao.save(board);
            return new ServiceStatusWithData(ServiceStatus.Status.Success, "保存成功").data(board);
        } else {
            return new ServiceStatusWithData(ServiceStatus.Status.Fail, "名称已存在");
        }
    }


    @SuppressWarnings({ "rawtypes", "unchecked" })
    public ServiceStatusWithData<DashboardBoard> update(String userId, String json) {
        JSONObject jsonObject = JSONObject.parseObject(json);
        DashboardBoard board = boardDao.getBoard(jsonObject.getLong("id"));
        if (null == board) {
            return new ServiceStatusWithData(ServiceStatus.Status.Fail, "数据不存在！");
        }
        board.setUserId(userId);
        board.setName(jsonObject.getString("name"));
        board.setCategoryId(jsonObject.getLong("categoryId"));
        board.setLayout(jsonObject.getString("layout"));
        board.setId(jsonObject.getLong("id"));

        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("board_id", board.getId());
        paramMap.put("user_id", board.getUserId());
        paramMap.put("board_name", board.getName());
        if (boardDao.countExistBoardName(paramMap) <= 0) {
            boardDao.update(board);
            return new ServiceStatusWithData(ServiceStatus.Status.Success, "修改成功").data(board);
        } else {
            return new ServiceStatusWithData(ServiceStatus.Status.Fail, "名称已存在");
        }
    }

    public ServiceStatus delete(String userId, Long id) {
        try {
            boardDao.delete(id, userId);
            return new ServiceStatus(ServiceStatus.Status.Success, "success");
        } catch (Exception e) {
            e.printStackTrace();
            return new ServiceStatus(ServiceStatus.Status.Fail, e.getMessage());
        }
    }

  public ServiceStatus checkIsWidgetStillDependent(String userId, Long widgetId) {
        List<DashboardBoard> dashboardBoardList = boardDao.getBoardList(userId);
        String regularExpression = "\"widgetId\":[0-9]+";
        Pattern pattern = Pattern.compile(regularExpression);//匹配的模式
        for (DashboardBoard dashboardBoard : dashboardBoardList) {
            String dataJson = dashboardBoard.getLayout();
            if (!StringUtils.isEmpty(dataJson)) {
                //使用正则表达式匹配获取对应的widget的id
                Matcher matcher = pattern.matcher(dataJson);
                while (matcher.find()) {
                    // widgetKeyValue 的格式为："widgetId":28
                    String widgetIdKeyValue = matcher.group(0);
                    String widgetIdValue = widgetIdKeyValue.split(":")[1];
                    if (widgetId.toString().equals(widgetIdValue)) {
                        return new ServiceStatus(ServiceStatus.Status.Fail, "删除失败，请检查对应的图表依赖配置");
                    }
                }
            }
        }
        return new ServiceStatus(ServiceStatus.Status.Success, "");
    }
    public byte[] exportBoard(Long id, String userId) {
        PersistContext persistContext = persistService.persist(id, userId);
        List<PersistContext> workbookList = new ArrayList<>();
        workbookList.add(persistContext);
        HSSFWorkbook workbook = xlsProcessService.dashboardToXls(workbookList);
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            workbook.write(outputStream);
            outputStream.close();
            return outputStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
	
	
    /**
     * @param userId
     * @param boardId
     * @param status
     * @return
     */
    public ServiceStatus publish(String address,Long userId, Long boardId, Integer status,String theme) {
        DashboardBoard board = boardDao.getBoard(boardId);
        if (null != board) {
            if (status == ServiceStatus.Status.Active.getStatus()) {//publish board
                try {
					String token = URLEncoder.encode(TokenUtils.genToken(boardId, userId,theme),"utf-8");
                    board.setPublishUrl(address + publishPath + token);
                } catch (Exception e) {
                    e.printStackTrace();
                    return new ServiceStatus(ServiceStatus.Status.Fail, "数据加密时发生错误！");
                }
            }
            board.setPublishStatus(status);
            /*board.setTheme(theme);*/
            boardDao.update(board);
            return new ServiceStatus(ServiceStatus.Status.Success, board.getPublishUrl());
        } else {
            return new ServiceStatus(ServiceStatus.Status.Fail, "记录不存在");
        }
    }

}
